package org.NooLab.glue.msgframe;

import java.util.*;

import org.NooLab.glue.components.GlobalReceipts;
import org.NooLab.glue.storage.MsgBoardDataStorage;
import org.NooLab.utilities.logging.PrintLog;

 


public class MetaRegistration {

	Vector<XRegistration> registeredInstances = new Vector<XRegistration>();
	
	Vector<Long> reservedIDs = new Vector<Long>();
	Map<Long, String> reservedIDnames = new TreeMap<Long, String>() ;

	int drawingNewId=0;
	

	GlobalReceipts globalReceipts ;
	MsgBoardDataStorage msgBoardStorage;
	
	PrintLog out = new PrintLog(2,true);
	
	
	public MetaRegistration( GlobalReceipts globalreceipts, MsgBoardDataStorage msgboardstorage){
		globalReceipts = globalreceipts ;
		msgBoardStorage = msgboardstorage;
	}

	public synchronized long getRegisteredIDSafely(){
		
		long rid=0, xregiid;
		boolean idNotOk=true;
		XRegistration xreg;
		
		/*
		if (drawingNewId>0){
			
			while (drawingNewId>0){
				delay(50);
				if (drawingNewId>0){
out.print(2, "metreg, drawing id , >>>> WAITING >>>> wait state: "+ drawingNewId);
					long rrid = getRegisteredIDSafely();
					return rrid;
				}
			}
		}
		*/
		drawingNewId++;
												out.print(4, "metreg, drawing id , wait state: "+ drawingNewId);		
		while (idNotOk){
			// 
			
			rid = globalReceipts.incGlobalRegisteredID();
		
			if ((reservedIDs.indexOf( rid)>=0)){
				rid = globalReceipts.incGlobalRegisteredID();
				continue;
			}
			
			// we have to check explicitly for potential collisions among the collection of registered items
			idNotOk = false;
			for (int i=0; i<registeredInstances.size();i++){
				xreg = registeredInstances.get(i) ;
				if (xreg != null) {
					xregiid = xreg.getInstanceID();
					if (xregiid >= rid) { // we make it strictly increasing!
						idNotOk = true;
						break;
					}
				}
			} // i-> registeredInstances
			
		} // -> idNotOk = false ?
		
		 
		msgBoardStorage.saveMsgBoardData() ;
		
		drawingNewId--;
												out.print(4, "metreg, drawing id , wait state: "+ drawingNewId);		
		return rid;
	}
	
	public synchronized long getSuggestionForID(String clientsName){

		long maxi=-1,suggID=-1, iid,z;
		
		for (int i = 0; i < registeredInstances.size(); i++) {
			iid = registeredInstances.get(i).instanceID;
			if (maxi < iid){
				maxi = iid ;
			}
			
		}

		if (reservedIDs.indexOf( maxi)<0){
			suggID = maxi+1;
		}else{
			z=0;
			while ((reservedIDs.indexOf( maxi)>=0) && (z<1000000)){
				maxi++;
				z++;
			} // ->
			
			if (reservedIDs.indexOf( maxi)<0){
				// if it is not in reservedIDs
				suggID = maxi ;
			}else{
				suggID = -1;
			}
		}
		if (suggID>0){
			reservedIDs.add(suggID) ;
			reservedIDnames.put(suggID, clientsName);
		}
		return suggID ;
	}
	

	public synchronized boolean registrationIsDuplicate( long iid){
		boolean rB=false;
		
		
		return rB;
	}
	
	/**
	 * modes: 1=registered?, 2=reserved, not registered
	 * 
	 * @param instanceID
	 * @param mode
	 * @return
	 */
	public Object iidIsRegisteredOrReserved( long instanceID, int mode){
		
		int index = -1;
		String name = "" ;
		Object obj=null ;
		XRegistration xreg;
		
		if (mode >=2 ){
			//Map<Long, String> reservedIDnames
			if (reservedIDnames.containsKey(instanceID) ){
				// 
				name = reservedIDnames.get(instanceID);
				obj = name;
			}
		}
		if (mode<=1){
			
			index = reservedIDs.indexOf(instanceID);
			xreg = this.getItemById(instanceID) ;
			if ((index<0) && (xreg!=null) && (((xreg.receptorState>0 ) || (xreg.receptorState<90)))){
				index = registeredInstances.indexOf(xreg) ;
			}
			obj = (Integer)index;
		}
		return obj;
	}
	
	/**
	 * 
	 * @param specString  "source" , "receptor", "iboard"
	 * @return
	 */
	public int countSpecifiedItems( String specString){ 
		int result = 0;
		XRegistration xreg ;
		
		for (int i=0;i<registeredInstances.size();i++){
			xreg = registeredInstances.get(i) ;
			if (xreg.getRole().toLowerCase().contains(specString)){
				result++;
			}
		}
		return result;
	}

	
	
	public int countSources(){
		return countSources(0) ;
	}
	
	public int countSources( int mode){
		return countClients(mode, "SOURCE");
	}
		
	public int countClients( int mode, String typelabel){	
		int result = 0, sv;
		boolean hb;
		XRegistration xreg ;
		
		for (int i=0;i<registeredInstances.size();i++){
			xreg = registeredInstances.get(i) ;
			if (xreg.getRole().toLowerCase().contains(typelabel)){
				sv = xreg.receptorState;
				hb=false;
				if (mode ==  0){ hb=true; } // count all
				if ((hb==false) && (mode == -1)){ hb = (sv==XRegistration.RST_IS_CLOSED) || (sv==XRegistration.RST_IS_TIMEDOUT); }
				if ((hb==false) && (mode == -2)){ hb = (sv==XRegistration.RST_IS_CLOSED) ; }
				if ((hb==false) && (mode == -3)){ hb = (sv==XRegistration.RST_IS_TIMEDOUT ); }
				if ((hb==false) && (mode ==  1)){ hb = (sv==XRegistration.RST_IS_STARTED ); }
				if ((hb==false) && (mode ==  2)){ hb = (sv>=XRegistration.RST_IS_STARTED ); }
				
				if (hb){ result++; }
			}
		}
		return result;
	}

	public int countReceptors(){
		return countReceptors(0) ;
	}
	
	public int countReceptors( int mode){
		return countClients(mode, "RECEPTOR");
	}
	
	 
	
	
	
	public int size(){
		return registeredInstances.size() ;
	}
	
	public void addItem( XRegistration xregItem){
		registeredInstances.add(xregItem) ;
	}

	public XRegistration getItem( int index ){
		
		return registeredInstances.get( index ) ;
	}

	public XRegistration getItemById( long instanceID){
		int p;
		XRegistration xreg=null;
		
		p = indexOf(instanceID);
		
		if (p>=0){
			xreg = registeredInstances.get(p) ;
		}
		return xreg;
	}
	
	public int getItemIndexById( long instanceID ){
		int p;
		
		p = indexOf(instanceID);

		return p;
	}
	
	
	public int indexOf(long instanceID){
		int index=-1;
		
		for (int i=0;i<registeredInstances.size();i++){
			if (registeredInstances.get(i).getInstanceID()==instanceID){
				index = i;
				break;
			}
		}
		
		return index;
	}
	
	public void removeItemByID( long instanceID ){
		int p;
		
		p = indexOf(instanceID);
		
		registeredInstances.set(p,null) ; 
		registeredInstances.remove(p) ;
	}
	

	
	public XRegistration removeItem( int index ){
		
		return registeredInstances.remove( index ) ;
	}
	
	
	public Vector<XRegistration> getRegisteredInstances() {
		return registeredInstances;
	}
	
	public Vector<Long> getReservedIDs() {
		return reservedIDs;
	}
	
	public Map<Long, String> getReservedIDnames() {
		return reservedIDnames;
	}

	@SuppressWarnings("static-access")
	private void delay(int millis){
	
		try{
			Thread.currentThread().sleep(millis) ;
		}catch(Exception e){}
	}
}
